﻿using System;
using System.Collections.Generic;
using System.Linq;
using Xunit;
using XunitExt;

namespace Rarous.NForms.Test {
  public class HtmlElementTest {
    public IEnumerable<string> EmptyTags { 
      get { 
        return new string[] { 
          "img", "hr", "br", "input", "meta", "area", "base", "col", "link", "param", "basefont", "frame", "isindex", 
          "wbr", "embed" };
      } 
    }

    [Fact]
    public void Default_tag_should_render_span_pair() {
      var el = new HtmlElement();

      el.OpeningTag.ShouldEqual("<span>");
      el.ClosingTag.ShouldEqual("</span>");
    }

    [Fact]
    public void Custom_pair_tag_should_have_opening_and_closing_tag() {
      var el = new HtmlElement("div");

      el.OpeningTag.ShouldEqual("<div>");
      el.ClosingTag.ShouldEqual("</div>");
    }

    [Fact]
    public void Empty_elements_should_have_empty_closing_tag() {
      foreach (string tagName in EmptyTags) {
        var el = new HtmlElement(tagName);

        el.OpeningTag.ShouldEqual("<" + tagName + " />");
        el.ClosingTag.ShouldEqual(String.Empty);
      }
    }

    [Fact]
    public void Element_without_tag_should_render_only_text() {
      var el = new HtmlElement(String.Empty, new { Text = "text" });

      el.OpeningTag.ShouldEqual(String.Empty);
      el.ClosingTag.ShouldEqual(String.Empty);
      el.ToString().ShouldEqual("text");
    }

    [Fact]
    public void Elememt_should_have_attributes() {
      var el = new HtmlElement("div", new { Class = "test" });

      el.Attributes["Class"].ShouldEqual("test");
      el["Class"].ShouldEqual("test");
      el.OpeningTag.ShouldEqual("<div class=\"test\">");
    }

    [Fact]
    public void Pseudoattribute_Text_should_render_tag_content() {
      var el = new HtmlElement("div", new { Text = "test" });

      el.ToString().ShouldEqual("<div>test</div>");
      el.Text.ShouldEqual("test");
    }

    [Fact]
    public void Element_should_render_itself_and_children() {
      var el = new HtmlElement("div");
      el.AddChild("div", new { Class = "header", Text = "test" });

      el.ToString().ShouldEqual("<div><div class=\"header\">test</div></div>");
    }

    [Fact]
    public void Element_with_text_and_children_renders_only_text() {
      var el = new HtmlElement("div", new { Text = "test" });
      el.AddChild("div", new { Class = "header", Text = "test" });

      el.ToString().ShouldEqual("<div>test</div>");
    }

    [Fact]
    public void Attribute_should_be_set_with_constructor_and_read_with_indexer() {
      var el = new HtmlElement("div", new { Class = "test" });

      el["Class"].ShouldEqual("test");
    }

    [Fact]
    public void Attribute_should_set_and_read_with_string_indexer() {
      var el = new HtmlElement();
      el["Class"] = "test";

      el["Class"].ShouldEqual("test");
    }

    [Fact]
    public void Element_should_recognize_that_have_setted_CSS_class() {
      var el = new HtmlElement("div", new { Class = "myClass" });

      el.HasClass("test").ShouldBeFalse();
      el.HasClass("myClass").ShouldBeTrue();
    }

    [Fact]
    public void Element_should_add_CSS_class() {
      var el = new HtmlElement();

      el.AddClass("test").HasClass("test").ShouldBeTrue();
    }

    [Fact]
    public void Element_should_add_and_remove_existing_CSS_class() {
      var el = new HtmlElement("div", new { Class = "test" });

      el.AddClass("test2");

      el.HasClass("test2").ShouldBeTrue();
      el.HasClass("test").ShouldBeTrue();

      el.RemoveClass("test");

      el.HasClass("test2").ShouldBeTrue();
      el.HasClass("test").ShouldBeFalse();
    }

    [Fact]
    public void Element_should_adopt_child() {
      var el = new HtmlElement();

      el.ChildrenCount.ShouldEqual(0);

      el.AddChild(new HtmlElement()).ChildrenCount.ShouldEqual(1);

      el[0].Parent.ShouldBeSameAs(el);

      el.AddChild("span").ChildrenCount.ShouldEqual(2);
    }

    [Fact]
    public void Elemet_should_set_HTML_content() {
      var el = new HtmlElement();

      el.SetHtml("<span>").Text.ShouldEqual("<span>");
    }
    
    [Fact]
    public void Elemet_should_set_encoded_text_content() {
      var el = new HtmlElement();

      el.SetText("<span>").Text.ShouldEqual("&lt;span&gt;");
    }

    [Fact]
    public void Element_should_iterate_child_elements() {
      var el = new HtmlElement();

      el.AddChild("span").AddChild("span").AddChild("span");

      foreach (var item in el) {
        item.ShouldBeType<HtmlElement>();
      }

    }

    [Fact]
    public void Elemet_should_be_enumerable() {
      var el = new HtmlElement();
      el.AddChild("span").AddChild("span").AddChild("span");

      var enumerable = (System.Collections.IEnumerable)el;

      foreach (object item in enumerable) {
        item.ShouldBeType<HtmlElement>();
      }

    }

  }
}
